package org.study.r2dbc.boot.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.study.r2dbc.boot.model.User;
import org.study.r2dbc.boot.service.UserServiceByRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

/**
 * 作用描述
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2025年04月02日
 */
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@RestController
@RequestMapping("/api/user/repository")
public class UserRepositoryController {
    private final UserServiceByRepository userServiceByRepository;

    @GetMapping
    public Flux<User> findAll() {
        return userServiceByRepository.findAll();
    }

    @GetMapping("/{id}")
    public Mono<User> findById(@PathVariable Long id) {
        return userServiceByRepository.findById(id);
    }

    @GetMapping("/name/{name}")
    public Flux<User> findByName(@PathVariable String name) {
        return userServiceByRepository.findByName(name);
    }

    @GetMapping("/email/{email}")
    public Flux<User> findByEmail(@PathVariable String email) {
        return userServiceByRepository.findByEmail(email);
    }

    @GetMapping("/age/{age}")
    public Flux<User> findByAgeGreaterThan(@PathVariable int age) {
        return userServiceByRepository.findByAgeGreaterThan(age);
    }

    @PostMapping("/saveUser")
    @ResponseStatus(HttpStatus.CREATED)
    public Mono<ResponseEntity<Map<String, Object>>> saveUser(@RequestBody User user) {
        Map<String, Object> map = new HashMap<>() {{
            this.put("timestamp", Instant.now());
        }};
        return userServiceByRepository.saveUser(user)
                .map(savedUser -> {
                    map.put("code", "0000");
                    map.put("status", "success");
                    map.put("msg", "保存成功");
                    map.put("data", savedUser);
                    return ResponseEntity.status(HttpStatus.CREATED).body(map);
                })
                .onErrorResume(ex -> {
                    map.put("code", "9999");
                    map.put("status", "fail");
                    map.put("msg", "保存失败");
                    map.put("data", null);
                    map.put("error", ex.getMessage());
                    return Mono.just(ResponseEntity.badRequest().body(map));
                });
    }

    @PutMapping("/{id}")
    public Mono<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        return userServiceByRepository.updateUser(id, user);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public Mono<Void> deleteUser(@PathVariable Long id) {
        return userServiceByRepository.deleteUser(id);
    }

    @DeleteMapping("/transferMoney/{fromId}/{toId}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public Mono<Void> transferMoney(@PathVariable("fromId") Long fromId,
                                    @PathVariable("toId") Long toId,
                                    @RequestParam(value = "amount", defaultValue = "1.00") BigDecimal amount) {
        return userServiceByRepository.transferMoney(fromId, toId, amount);
    }
}
